package com.zjh.simpledao.util;

import com.zjh.simpledao.datasource.SimpleDateSource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * @author zjh
 * @version V1.0.0
 * @date 2019/2/21 15:36
 * @since 1.0
 */
public class DButil {

  /**
   * 插入方法
   *
   * @param t
   * @param <T>
   */
  public <T> void insert(T t) {
    SimpleDateSource instance;
    Connection connection = null;
    PreparedStatement stmt = null;
    instance = SimpleDateSource.instance();
    try {
      connection = instance.getConnection();
      String insertSqlFromIntity = ReflectionUtil.getInsertSqlFromIntity(t.getClass());
      List<String> columnlFromIntity = ReflectionUtil.getColumnlListFromIntity(t.getClass());
      stmt = connection.prepareStatement(insertSqlFromIntity);
      for (int i = 0; i < columnlFromIntity.size(); i++) {
        String column = columnlFromIntity.get(i);
        Method m = t.getClass().getDeclaredMethod("get" + StringUtils.toUpperCaseFirstOne(column));
        stmt.setObject(i + 1, m.invoke(t));
      }
      stmt.execute();
    } catch (SQLException
        | NoSuchMethodException
        | IllegalAccessException
        | InvocationTargetException e) {
      e.printStackTrace();
    } finally {
      closeAll(null, stmt, connection);
    }
  }
  /**
   * 查询方法
   *
   * @param t
   * @param <T>
   */
  public <T> T select(T t) {
    SimpleDateSource instance;
    Connection connection = null;
    PreparedStatement stmt = null;
    ResultSet resultSet = null;
    instance = SimpleDateSource.instance();
    T o = null;
    try {
      o = (T) t.getClass().newInstance();
      connection = instance.getConnection();
      String selectSqlFromIntity = ReflectionUtil.getSelectSqlFromIntity(t.getClass());
      List<String> columnlFromIntity = ReflectionUtil.getColumnlListFromIntity(t.getClass());
      stmt = connection.prepareStatement(selectSqlFromIntity);
      Method m =
          t.getClass()
              .getDeclaredMethod(
                  "get" + StringUtils.toUpperCaseFirstOne(ReflectionUtil.getPkName(t.getClass())));
      stmt.setObject(1, m.invoke(t));
      resultSet = stmt.executeQuery();
      columnlFromIntity.add(ReflectionUtil.getPkName(t.getClass()));
      while (resultSet.next()) {
        for (int i = 0; i < columnlFromIntity.size(); i++) {
          Object object = resultSet.getObject(columnlFromIntity.get(i));
          Method method =
              t.getClass()
                  .getDeclaredMethod(
                      "set" + StringUtils.toUpperCaseFirstOne(columnlFromIntity.get(i)),
                      t.getClass().getDeclaredField(columnlFromIntity.get(i)).getType());
          method.invoke(o, object);
        }
      }
    } catch (SQLException
        | IllegalAccessException
        | InstantiationException
        | NoSuchMethodException
        | InvocationTargetException
        | NoSuchFieldException e) {
      e.printStackTrace();
    } finally {
      closeAll(resultSet, stmt, connection);
    }
    return o;
  }
  /**
   * 更新方法
   *
   * @param t
   * @param <T>
   */
  public <T> void updateById(T t) {
    SimpleDateSource instance;
    Connection connection = null;
    PreparedStatement stmt = null;
    instance = SimpleDateSource.instance();
    try {
      connection = instance.getConnection();
      String updateSql = ReflectionUtil.getUpdateSqlFromIntity(t.getClass());
      List<String> columnlFromIntity = ReflectionUtil.getColumnlListFromIntity(t.getClass());
      columnlFromIntity.add(ReflectionUtil.getPkName(t.getClass()));
      stmt = connection.prepareStatement(updateSql);
      for (int i = 0; i < columnlFromIntity.size(); i++) {
        String column = columnlFromIntity.get(i);
        Method m = t.getClass().getDeclaredMethod("get" + StringUtils.toUpperCaseFirstOne(column));
        stmt.setObject(i + 1, m.invoke(t));
      }
      stmt.execute();
    } catch (SQLException
        | NoSuchMethodException
        | IllegalAccessException
        | InvocationTargetException e) {
      e.printStackTrace();
    } finally {
      closeAll(null, stmt, connection);
    }
  }
  /**
   * 删除方法
   *
   * @param t
   * @param <T>
   */
  public <T> void deleteById(T t) {
    SimpleDateSource instance;
    Connection connection = null;
    PreparedStatement stmt = null;
    instance = SimpleDateSource.instance();
    try {
      connection = instance.getConnection();
      String deleteSql = ReflectionUtil.getDeleteSqlFromIntity(t.getClass());
      stmt = connection.prepareStatement(deleteSql);
      Method m =
          t.getClass()
              .getDeclaredMethod(
                  "get" + StringUtils.toUpperCaseFirstOne(ReflectionUtil.getPkName(t.getClass())));
      stmt.setObject(1, m.invoke(t));
      stmt.execute();
    } catch (SQLException
        | NoSuchMethodException
        | IllegalAccessException
        | InvocationTargetException e) {
      e.printStackTrace();
    } finally {
      closeAll(null, stmt, connection);
    }
  }

  /**
   * 释放资源
   *
   * @param rs
   * @param stmt
   * @param conn
   */
  public static void closeAll(ResultSet rs, PreparedStatement stmt, Connection conn) {
    if (rs != null) {
      try {
        rs.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    if (stmt != null) {
      try {
        stmt.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    if (conn != null) {
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
  }
}
